/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Module Name          : com.yaodian100.ec.generatepage.web.GeneratePageAction
   Module Description   :

   Date Created      : 2009/12/17
   Original Author   : feeling.wang
   Team              : yaodian100
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   MODIFICATION HISTORY
   ------------------------------------------------------------------------------
   Date Modified       Modified by       Comments
   ------------------------------------------------------------------------------
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
package com.yaodian100.ec.generatepage.web;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.commons.lang.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opensymphony.xwork2.ActionSupport;
import com.yaodian100.core.common.dao.impl.CommonCriteria;
import com.yaodian100.core.common.exception.CoreException;
import com.yaodian100.core.common.service.DomainService;
import com.yaodian100.core.common.utils.ServerValue;
import com.yaodian100.core.menu.entity.Menu;
import com.yaodian100.core.template.service.TemplateService;
import com.yaodian100.ec.common.EcConstant;
import com.yaodian100.ec.generate.service.GenerateOrderService;
import com.yaodian100.ec.member.entity.Member;
import com.yaodian100.ec.member.service.MemberService;
import com.yaodian100.ec.order.entity.Orders;
import com.yaodian100.ec.order.service.OrderService;

/**
 * @author feeling.wang
 * 
 */
public class GeneratePageAction extends ActionSupport {

	private static final long serialVersionUID = 3256969043791455694L;

	/** logger */
	private final Logger logger = LoggerFactory.getLogger(GeneratePageAction.class);

	private Menu orderStMenu; // 與 getter, setter
	private Menu paymentStMenu; // 與 getter, setter
	private Menu paymentTpMenu; // 與 getter, setter
	private Menu logisticStMenu; // 與 getter, setter
	private Menu returnStMenu; // 與 getter, setter

	private DomainService<Menu> menuService; // 與 setter
	private OrderService orderService;
	private MemberService memberService;
	private TemplateService velocityService;
	private List<Orders> orders;
	private List<Member> members;
	private String memberId;
	private Map<String, Object> paramMap = new HashMap<String, Object>();
	private CommonCriteria criteria = null;

	private static String zeroToFour;
	private static String fiveToEight;
	private static StringBuilder memberFilePath = new StringBuilder("");
	private static StringBuilder mkDir_zeroToFour = new StringBuilder("");
	private static StringBuilder mkDir_fiveToEight = new StringBuilder("");
	private static StringBuilder memberFileName = new StringBuilder("");
	private static final String subFileName = ".html";
	private static final int orderPageRecord = 2;
	private static final int memberPageRecord = 10;
	private List<Orders> tmpOrder = new ArrayList<Orders>();
	private final StringBuilder T_ORDER = new StringBuilder("");
	private final StringBuilder H_ORDER = new StringBuilder("");
	@Resource
	private GenerateOrderService generateOrderService;

	/**
	 * 批次產生所有會員的靜態訂單頁面
	 * 
	 * @return
	 * @throws Exception
	 */
	public String generateAllOrder() throws Exception {
		initMenu();
		int memberCount = memberService.getAllSize().intValue();
		int totalPage = memberCount % memberPageRecord != 0 ? (memberCount / memberPageRecord) + 1 : memberCount
				/ memberPageRecord;
		for (int i = 0; i < totalPage; i++) {
			members = memberService.getAll(i * memberPageRecord, memberPageRecord, new String[] { "memberId" });
			for (int j = 0; j < members.size(); j++) {
				mkDir(members.get(j).getMemberId());
				generateOrder(members.get(j).getMemberId());
				generateYetPaymentOrder(members.get(j).getMemberId());
				generateHistoryOrder(members.get(j).getMemberId());
			}
		}
		return SUCCESS;
	}

	/**
	 * 查詢歷史訂單
	 * 
	 * @return
	 * @throws CoreException
	 */
	private void generateHistoryOrder(String memberId) throws CoreException {
		try {
			CommonCriteria criteria = getOrderCommonCriteria(memberId, "H");
			int historyOrderCount = orderService.getListSize(criteria).intValue();
			int totalPage = historyOrderCount % orderPageRecord != 0 ? (historyOrderCount / orderPageRecord) + 1
					: historyOrderCount / orderPageRecord;
			paramMap = getCommonParamMap(totalPage, "H", historyOrderCount);
			int p = 0;
			if (totalPage == 0) {
				p = 1;
				paramMap.put("totalCount_H", 0);
				writeStaticFile(paramMap, memberId, "H", p);
			} else {
				orders = orderService.getList(0, -1, criteria, new String[] { "orderDt" });
				List<Orders> tmpOrder = new ArrayList<Orders>();
				// tmpOrder.addAll(orders);
				for (int i = 0; i < totalPage; i++) {
					p = i + 1;
					tmpOrder = orders.subList(i * orderPageRecord, orderPageRecord * p > historyOrderCount ? historyOrderCount
							: orderPageRecord * p);
					paramMap.put("orders", tmpOrder);
					paramMap.put("currentPage", p);
					paramMap.put("totalCount_H", historyOrderCount);
					writeStaticFile(paramMap, memberId, "H", p);
				}
			}
		} catch (ParseException e) {
			addActionError("日期轉換錯誤");
		} catch (IOException e) {
			addActionError("檔案寫入失敗");
		} catch (Exception e) {
			addActionError("Menu產生錯誤");
		}
	}

	public String generateMemberOrder() throws Exception {
		generateOrderService.generateMemberOrderPage(memberId);
		return SUCCESS;
	}

	/**
	 * 所有訂單(2個月內的資料)
	 * 
	 * @throws CoreException
	 */
	private void generateOrder(String memberId) throws CoreException {
		try {
			criteria = getOrderCommonCriteria(memberId, "T");
			int orderCount = getOrderCount(criteria);
			int totalPage = orderCount % orderPageRecord != 0 ? (orderCount / orderPageRecord) + 1 : orderCount
					/ orderPageRecord;
			int p = 0;
			paramMap = getCommonParamMap(totalPage, "T", orderCount);
			if (totalPage == 0) {// 0筆資料
				p = 1;
				paramMap.put("totalCount_T", orderCount);
				paramMap.put("totalCount_Y", 0);
				writeStaticFile(paramMap, memberId, "T", p);
			} else {
				orders = orderService.getList(0, -1, criteria, new String[] { "orderDt" });
				List<Orders> tmpOrder = new ArrayList<Orders>();
				logger.info("=== generateOrder criteria ===:{}", criteria);
				for (int i = 0; i < totalPage; i++) {
					p = i + 1;
					tmpOrder = orders.subList(i * orderPageRecord, orderPageRecord * p > orderCount ? orderCount
							: orderPageRecord * p);
					paramMap.put("orders", tmpOrder);
					paramMap.put("currentPage", p);
					paramMap.put("totalCount_T", orderCount);
					// 未支付訂單筆數
					criteria = getOrderCommonCriteria(memberId, "Y");
					int yetPaymentOrderCount = getOrderCount(criteria);
					paramMap.put("totalCount_Y", yetPaymentOrderCount);
					writeStaticFile(paramMap, memberId, "T", p);
				}
			}
		} catch (ParseException e) {
			addActionError("日期轉換錯誤");
		} catch (IOException e) {
			addActionError("檔案寫入失敗");
		} catch (Exception e) {
			addActionError("Menu產生錯誤");
		}
	}

	/**
	 * 查詢交易中未付款之訂單(2個月內)
	 * 
	 * @return
	 * @throws CoreException
	 */
	private void generateYetPaymentOrder(String memberId) throws CoreException {
		try {
			CommonCriteria criteria = getOrderCommonCriteria(memberId, "Y");
			int yetPaymentOrderCount = orderService.getListSize(criteria).intValue();
			int totalPage = yetPaymentOrderCount % orderPageRecord != 0 ? (yetPaymentOrderCount / orderPageRecord) + 1
					: yetPaymentOrderCount / orderPageRecord;
			int p = 0;
			paramMap = getCommonParamMap(totalPage, "Y", yetPaymentOrderCount);
			if (totalPage == 0) {
				p = 1;
				paramMap.put("totalCount_Y", 0);
				paramMap.put("totalCount_T", 0);
				writeStaticFile(paramMap, memberId, "Y", p);
			} else {
				orders = orderService.getList(0, -1, criteria, new String[] { "orderDt" });
				for (int i = 0; i < totalPage; i++) {
					p = i + 1;
					tmpOrder = orders.subList(i * orderPageRecord,
							orderPageRecord * p > yetPaymentOrderCount ? yetPaymentOrderCount : orderPageRecord * p);
					paramMap.put("orders", tmpOrder);
					paramMap.put("currentPage", p);
					paramMap.put("totalCount_Y", yetPaymentOrderCount);
					criteria = getOrderCommonCriteria(memberId, "T");
					int orderCount = getOrderCount(criteria);
					paramMap.put("totalCount_T", orderCount);
					writeStaticFile(paramMap, memberId, "Y", p);
				}
			}
		} catch (ParseException e) {
			addActionError("日期轉換錯誤");
		} catch (IOException e) {
			addActionError("檔案寫入失敗");
		} catch (Exception e) {
			addActionError("Menu產生錯誤");
		}
	}

	/**
	 * 組出我的訂單、未付款訂單、歷史訂單共用的map參數
	 * 
	 * @param totalPage
	 * @param orderType
	 * @param totalCount
	 * @return
	 */
	Map<String, Object> getCommonParamMap(int totalPage, String orderType, int totalCount) {
		paramMap.put("totalPage", totalPage);
		paramMap.put("orderType", orderType);
		paramMap.put("totalCount", totalCount);
		return paramMap;
	}

	/**
	 * 取得會員檔案存放路徑
	 * 
	 * @param memberId
	 * @return
	 * @throws Exception
	 */
	private String getMemberFilePath(String memberId) throws Exception {
		zeroToFour = memberId.substring(0, 4);
		fiveToEight = memberId.substring(4, 8);
		// 清空上一位memberfilepath
		memberFilePath.setLength(0);
		memberFilePath.append(ServerValue.getFrontOrderHtmlPath()).append(zeroToFour).append("/").append(fiveToEight)
				.append("/").append(memberId);
		return memberFilePath.toString();
	}

	public String getMemberId() {
		return memberId;
	}

	/**
	 * 依類別組出查詢條件
	 * 
	 * @param memberId
	 * @param orderType
	 * @return
	 * @throws CoreException
	 * @throws ParseException
	 */
	CommonCriteria getOrderCommonCriteria(String memberId, String orderType) throws CoreException, ParseException {
		criteria = new CommonCriteria();
		criteria.addEq("memberId", memberId);
		if ("T".equalsIgnoreCase(orderType)) {
			criteria.addGe("orderDt", DateUtils.parseDate(FastDateFormat.getInstance(EcConstant.MIN_PATTERN_TIMESTAMP)
					.format(DateUtils.addDays(new Date(), -59)), new String[] { EcConstant.PATTERN_TIMESTAMP }));
			criteria.addLe("orderDt", DateUtils.parseDate(FastDateFormat.getInstance(EcConstant.MAX_PATTERN_TIMESTAMP)
					.format(new Date()), new String[] { EcConstant.PATTERN_TIMESTAMP }));
		}
		if ("Y".equalsIgnoreCase(orderType)) {
			criteria.addEq("paymentSt", "00");
			criteria.addGe("orderDt", DateUtils.parseDate(FastDateFormat.getInstance(EcConstant.MIN_PATTERN_TIMESTAMP)
					.format(DateUtils.addDays(new Date(), -59)), new String[] { EcConstant.PATTERN_TIMESTAMP }));
			criteria.addLe("orderDt", DateUtils.parseDate(FastDateFormat.getInstance(EcConstant.MAX_PATTERN_TIMESTAMP)
					.format(new Date()), new String[] { EcConstant.PATTERN_TIMESTAMP }));
		}
		if ("H".equalsIgnoreCase(orderType)) {
			criteria.addLe("orderDt", DateUtils.addDays(new Date(), -60));
		}
		return criteria;
	}

	/**
	 * 查詢訂單筆數
	 * 
	 * @param criteria
	 * @return
	 * @throws CoreException
	 */
	int getOrderCount(CommonCriteria criteria) throws CoreException {
		int count = orderService.getListSize(criteria).intValue();
		return count;
	}

	/**
	 * 初始化menu資料
	 * 
	 * @throws Exception
	 */
	public void initMenu() throws Exception {
		if (orderStMenu == null) {
			orderStMenu = menuService.get("Order.status");
			paramMap.put("orderStMenu", orderStMenu);
		}
		if (logisticStMenu == null) {
			logisticStMenu = menuService.get("Order.Prod.LogisticSt");
			paramMap.put("logisticStMenu", logisticStMenu);
		}
		if (paymentStMenu == null) {
			paymentStMenu = menuService.get("Order.paymentSt");
			paramMap.put("paymentStMenu", paymentStMenu);
		}
		if (paymentTpMenu == null) {
			paymentTpMenu = menuService.get("Order.PaymentTp");
			paramMap.put("paymentTpMenu", paymentTpMenu);
		}
		if (returnStMenu == null) {
			returnStMenu = menuService.get("Order.Prod.ReturnSt");
			paramMap.put("returnStMenu", returnStMenu);
		}
	}

	/**
	 * 建会员目录,刪除訂單資料
	 * 
	 * @throws Exception
	 * 
	 * @throws Exception
	 */
	void mkDir(String memberId) throws Exception {
		zeroToFour = memberId.substring(0, 4);
		fiveToEight = memberId.substring(4, 8);
		mkDir_zeroToFour = mkDir_zeroToFour.append(ServerValue.getFrontOrderHtmlPath()).append("/").append(zeroToFour);
		mkDir_fiveToEight = mkDir_zeroToFour.append("/").append(fiveToEight);
		if (!new File(mkDir_zeroToFour.toString()).exists()) {
			FileUtils.forceMkdir(new File(mkDir_zeroToFour.toString()));
			if (!new File(mkDir_fiveToEight.toString()).exists()) {
				FileUtils.forceMkdir(new File(mkDir_fiveToEight.toString()));
			}
		} else {
			if (!new File(mkDir_fiveToEight.toString()).exists()) {
				FileUtils.forceMkdir(new File(mkDir_fiveToEight.toString()));
			}
		}
		if (!new File(getMemberFilePath(memberId)).exists())
			FileUtils.forceMkdir(new File(getMemberFilePath(memberId)));
		else {
			/* 刪除會員訂單頁面 */
			File file = new File(getMemberFilePath(memberId));
			// File[] files = file.listFiles();
			T_ORDER.append(memberId).append("_T_");
			H_ORDER.append(memberId).append("_H_");
			File[] files = file.listFiles(new FilenameFilter() {

				public boolean accept(File dir, String name) {
					return (name.contains(T_ORDER) || name.contains(H_ORDER));
				}
			});

			if (null != files) {
				for (int i = 0; i < files.length; i++) {
					FileUtils.forceDelete(files[i]);
				}
			}
		}
		mkDir_zeroToFour.setLength(0);
		mkDir_fiveToEight.setLength(0);
		T_ORDER.setLength(0);
		H_ORDER.setLength(0);
	}

	public void setLogisticStMenu(Menu logisticStMenu) {
		this.logisticStMenu = logisticStMenu;
	}

	public void setMemberId(String memberId) {
		this.memberId = memberId;
	}

	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}

	public void setMenuService(DomainService<Menu> menuService) {
		this.menuService = menuService;
	}

	public void setOrderService(OrderService orderService) {
		this.orderService = orderService;
	}

	public void setOrderStMenu(Menu orderStMenu) {
		this.orderStMenu = orderStMenu;
	}

	public void setPaymentStMenu(Menu paymentStMenu) {
		this.paymentStMenu = paymentStMenu;
	}

	public void setPaymentTpMenu(Menu paymentTpMenu) {
		this.paymentTpMenu = paymentTpMenu;
	}

	public void setReturnStMenu(Menu returnStMenu) {
		this.returnStMenu = returnStMenu;
	}

	public void setVelocityService(TemplateService velocityService) {
		this.velocityService = velocityService;
	}

	/**
	 * 寫入訂單靜態檔案
	 * 
	 * @param paramMap
	 * @param memberId
	 * @param orderType
	 * @param page
	 * @throws Exception
	 */
	void writeStaticFile(Map<String, Object> paramMap, String memberId, String orderType, int page) throws Exception {
		try {
			String fileContent = velocityService.format("member.transactionOrder", paramMap);
			memberFileName.append(getMemberFilePath(memberId)).append("\\").append(memberId).append("_").append(orderType)
					.append("_").append(page).append(subFileName);
			File file = new File(memberFileName.toString());
			FileUtils.writeStringToFile(file, fileContent);
			memberFileName.setLength(0);
		} catch (CoreException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}